<template>
  <div id="X6DAG-container"></div>
</template>

<script setup lang="ts">
import { onMounted } from 'vue'
import { Graph, Platform } from '@antv/x6'
import { Selection } from '@antv/x6-plugin-selection'
import { useRegisterResource } from './hooks/useRegisterResource'
import dataProcessingDag from './data-processing-dag.json'

defineOptions({
  name: 'X6DAGDemo'
})

useRegisterResource()

onMounted(() => {
  const graph: Graph = new Graph({
    container: document.getElementById('X6DAG-container')!,
    panning: {
      enabled: true,
      eventTypes: ['leftMouseDown', 'mouseWheel']
    },
    mousewheel: {
      enabled: true,
      modifiers: 'ctrl',
      factor: 1.1,
      maxScale: 1.5,
      minScale: 0.5
    },
    highlighting: {
      magnetAdsorbed: {
        name: 'stroke',
        args: {
          attrs: {
            fill: '#fff',
            stroke: '#31d0c6',
            strokeWidth: 4
          }
        }
      }
    },
    connecting: {
      snap: true,
      allowBlank: false,
      allowLoop: false,
      highlight: true,
      sourceAnchor: {
        name: 'left',
        args: {
          dx: Platform.IS_SAFARI ? 4 : 8
        }
      },
      targetAnchor: {
        name: 'right',
        args: {
          dx: Platform.IS_SAFARI ? 4 : -8
        }
      },
      createEdge() {
        return graph.createEdge({
          shape: 'data-processing-curve',
          attrs: {
            line: {
              strokeDasharray: '5 5'
            }
          },
          zIndex: -1
        })
      },
      // 连接桩校验
      validateConnection({ sourceMagnet, targetMagnet }) {
        // 只能从输出链接桩创建连接
        if (!sourceMagnet || sourceMagnet.getAttribute('port-group') === 'in') {
          return false
        }
        // 只能连接到输入链接桩
        if (!targetMagnet || targetMagnet.getAttribute('port-group') !== 'in') {
          return false
        }
        return true
      }
    }
  })

  graph.use(
    new Selection({
      multiple: true,
      rubberEdge: true,
      rubberNode: true,
      modifiers: 'shift',
      rubberband: true
    })
  )

  // 节点状态列表
  const nodeStatusList = [
    {
      id: 'node-0',
      status: 'success'
    },
    {
      id: 'node-1',
      status: 'success'
    },
    {
      id: 'node-2',
      status: 'success'
    },
    {
      id: 'node-3',
      status: 'success'
    },
    {
      id: 'node-4',
      status: 'error',
      statusMsg: '错误信息示例'
    }
  ]

  // 边状态列表
  const edgeStatusList = [
    {
      id: 'edge-0',
      status: 'success'
    },
    {
      id: 'edge-1',
      status: 'success'
    },
    {
      id: 'edge-2',
      status: 'success'
    },
    {
      id: 'edge-3',
      status: 'success'
    }
  ]

  // 显示节点状态
  const showNodeStatus = () => {
    nodeStatusList.forEach((item) => {
      const { id, status, statusMsg } = item
      const node = graph.getCellById(id)
      const data = node.getData() as any
      node.setData({
        ...data,
        status,
        statusMsg
      })
    })
  }

  // 开启边的运行动画
  const excuteAnimate = () => {
    graph.getEdges().forEach((edge) => {
      edge.attr({
        line: {
          stroke: '#3471F9'
        }
      })
      edge.attr('line/strokeDasharray', 5)
      edge.attr('line/style/animation', 'running-line 30s infinite linear')
    })
  }

  // 关闭边的动画
  const stopAnimate = () => {
    graph.getEdges().forEach((edge) => {
      edge.attr('line/strokeDasharray', 0)
      edge.attr('line/style/animation', '')
    })
    edgeStatusList.forEach((item) => {
      const { id, status } = item
      const edge = graph.getCellById(id)
      if (status === 'success') {
        edge.attr('line/stroke', '#52c41a')
      }
      if (status === 'error') {
        edge.attr('line/stroke', '#ff4d4f')
      }
    })
    // 默认选中一个节点
    graph.select('node-2')
  }

  graph.fromJSON(dataProcessingDag)
  const zoomOptions = {
    padding: {
      left: 10,
      right: 10
    }
  }
  graph.zoomToFit(zoomOptions)
  setTimeout(() => {
    excuteAnimate()
  }, 2000)
  setTimeout(() => {
    showNodeStatus()
    stopAnimate()
  }, 3000)
})
</script>

<style lang="scss" scoped>
#X6DAG-container {
  height: 100%;
  width: 100%;
}
</style>
